﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Conan.Options;
using ConanLib;

namespace Conan
{
    class Program
    {
        static void Main(string[] args)
        {
            string _filePath = null;
            string _outDir = Environment.CurrentDirectory;
            int _outFilter = 1;
            double foldChange = 1;
            double _minPCC = 0.9;
            bool _log2Transform = false;
            bool _subNetworks = true;
            bool _graphics = true;
            bool _showHelp = false;
            int _take = 0;
            int _skip = 1;
            int _minVectorLength = 1;
            int _dpi = 96;
            bool _outputSubnetworks = false;
            string _correlation = "pearson";
            string _sideLoadFile = "";

            LayoutAlgorithm _la = LayoutAlgorithm.FMR;
            string layoutLags = @"circle - Circle
fmr - FructermanReingold
grid - Grid
hkfm - HarelKorenFastMultiscale
rand - Random
polar - Polar
sinus - Sinus
spiral - Spiral
sugi - Sugiyama
";
            OptionSet os = new OptionSet {
                            {"r|correlation=", "The name of the {CORRELATION ALGORITHM} used. Default Pearson Correlation. The other option is Spearman",     v => _correlation = v },
   	                        {"i|file=", "The path of the input {FILE} to process.",     v => _filePath = v },
                            {"a|sideload=", "The path of the input {FILE} that contains prprocessed relationships.",     v => _sideLoadFile = v },
                            {"o|outdir=", "The path of the {OUTPUT_DIRECTORY} to save the results. Default is the current directory.",     v => _outDir = v },
                            { "s|skip=", "Skips {LINECOUNT} from the input file. Skip is always at least 1 because it skips the header", v => {_skip = int.Parse(v);}  },
                            { "t|take=", "Takes top {LINECOUNT} from the input file. Will be apllied after skip. Zero means read all. The default is 0.", v => {_take = int.Parse(v);}  },
                            { "f|foldchange=", "The {FOLDCHANGE} treshhold for pre-filtering the data. The default is 1 for no pre-filtering.",  v => {foldChange = double.Parse(v);}  } ,
                            { "g|log2transformation=",  "An {BOOLEAN} value that indicates whether to apply a log2 transformation or not. The default is false.",   v => {_log2Transform = bool.Parse(v);}  },
                            { "c|cc=",  "The minimum {PCC} or {SCC} for building the network. The default is 0.9",   v => {_minPCC = double.Parse(v);}  },
                            { "l|minvectorlength=",  "The minimum length of vector included for network build. Default is 1",   v => {_minVectorLength = int.Parse(v);}  },
                            { "u|subnetworks=", "A {BOOLEAN} value that indicates whether to cluster subnetworks",  v => {_subNetworks = bool.Parse(v);}  },
                            { "v|outsubnetworks=", "A {BOOLEAN} value that indicates whether to output individual files for each subnetwork",  v => {_outputSubnetworks = bool.Parse(v);}  },
                            { "e|minvertexfilter=", "A {NUMBER} to filter the output of networks with minimal number of vertices. The default is 1 and so that all networks are written.",  v => {_outFilter = int.Parse(v);}  },
                            { "x|graphics=", "A {BOOLEAN} value that indicates whether to generate graphics for each network.",  v => {_graphics = bool.Parse(v);}  },
                            { "y|layout=", "A {TEXT} value that indicates which layout to use for graph generation. Default fmr - FruchtermanReingold\r\n"  + layoutLags,  v => {_la = (LayoutAlgorithm)Enum.Parse(typeof(LayoutAlgorithm), v.ToUpper());}  },
                            { "d|dpi=", "The targrt {DPI} value to render graphics.",  v => {_dpi = Int32.Parse(v);}  },
   	                        { "h|help",  "show this message and exit",                v => _showHelp = v != null }, 
            };

            try
            {

                List<string> extra;
                extra = os.Parse(args);
                if (_showHelp)
                {
                    ShowHelp(os);
                    return;
                }
                if (string.IsNullOrEmpty(_filePath) && string.IsNullOrEmpty(_sideLoadFile))
                {
                    Console.Write("CO.N.AN: ");
                    Console.WriteLine("No input file specified.");
                    Console.WriteLine("Try conan --help' for more information.");
                    //  Console.WriteLine("...press enter to quit");
                    Console.ReadLine();
                    return;
                }
            }
            catch (OptionException e)
            {
                Console.Write("CO.N.AN: ");
                Console.WriteLine(e.Message);
                Console.WriteLine("Try conan --help' for more information.");
                //   Console.WriteLine("...press enter to quit");
                Console.ReadLine();
                return;
            }

            RunConfiguration config = new RunConfiguration();
            if (_correlation.Trim().ToLower() == "pearson")
                config.CCType = CorrelationCoefficient.PEARSON;
            else if (_correlation.Trim().ToLower() == "spearman")
                config.CCType = CorrelationCoefficient.SPEARMAN;
            else
                throw new ArgumentException("Unknown correlation calculation '{0}'", _correlation);

            config.Layout = _la;
            config.DoLogTransformation = _log2Transform;
            config.DoSubNetworks = _subNetworks;
            config.GenerateGraphics = _graphics;
            config.GraphicsDPI = _dpi;
            config.InputFile = _filePath;
            config.MinCorrelationCoefficientFilter = Math.Abs(_minPCC);
            config.MinFoldChangeFilter = foldChange;
            config.MinVectorLengthFilter = _minVectorLength;
            config.MinVertexOutputFilter = _outFilter;
            config.OutputDir = _outDir;
            config.Skip = _skip;
            config.Take = _take;
            config.DoOutputSubNetworks = _outputSubnetworks;
            config.SideLoadFile = _sideLoadFile;
            if (!string.IsNullOrEmpty(_sideLoadFile))
            {
                config.PerformSideLoad = true;
            }

            Pipeline pipe = new Pipeline();
            pipe.Run(config);

        }



        //show help menu
        private static void ShowHelp(OptionSet os)
        {
            Console.WriteLine("Usage: conan -i filename [OPTIONS]");
            Console.WriteLine();
            Console.WriteLine("Options:");
            os.WriteOptionDescriptions(Console.Out);
        }
    }

}
